package com.zytech.zspider.task.impl;

import com.google.common.base.Objects;
import com.zytech.modules.lang.Langs;
import com.zytech.zspider.core.TaskDefinition;
import com.zytech.zspider.core.TaskResult;
import com.zytech.zspider.core.TaskResultPipelineSettings;
import com.zytech.zspider.logger.Loggers;
import com.zytech.zspider.task.*;

import java.util.Random;

/**
 * @author siuming
 */
public final class TaskResultRetryHandler implements TaskResultHandler {

    @Override
    public TaskResult onResult(TaskExecutor executor,
                               TaskDefinition task,
                               TaskContext context,
                               TaskResult result) {

        TaskResultPipelineSettings settings = task.getPipelineSettings();
        if (null == settings || !settings.isRequiresRetry()) {
            return result;
        }

        TaskResult usingResult = result;
        int retryTimes = settings.getRetryTimes();

        while (retryTimes-- > 0) {
            try {

                context.putBinding(TaskContext.TASK_RESULT, usingResult);
                Object value = executor.getExpressionEvaluator().eval(settings.getRetryWhen(), context);
                if (!Objects.equal(Boolean.TRUE, value)) {
                    break;
                }

                long sleepMillis = new Random().nextInt(500) + 500;
                Loggers.me().warn(getClass(), "sleep {} ms and retry {} again.", sleepMillis, task);
                Langs.sleepQuietly(sleepMillis);
                usingResult = executor.retryTask(task, context);
            } finally {
                context.putBinding(TaskContext.TASK_RESULT, TaskResult.EMPTY);
            }

        }

        return usingResult;
    }
}
